﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using LibraryMusicStore;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.DXErrorProvider;
using DevExpress.XtraGrid.Views.Base;

namespace AppMusicStore
{
    public partial class frmReceiptEditor : DevExpress.XtraEditors.XtraForm
    {
        IRepository<ReceiptDetail> rdRepository;
        IRepository<Receipt> receiptRepository;
        IRepository<Album> albumRepository;
        IRepository<Provider> providerRepository;
        internal int? id;
        DataTable dt;

        public IRepository<Receipt> ReceiptRepository
        {
            get { return receiptRepository; }
            set { receiptRepository = value; }
        }

        public DataTable Dt
        {
            get { return dt; }
            set { dt = value; }
        }

        public frmReceiptEditor()
        {
            InitializeComponent();
        }

        private void frmAlbumEditor_Load(object sender, EventArgs e)
        {
            try
            {
                //receiptRepository = new Repository<Receipt>();
                rdRepository = new Repository<ReceiptDetail>(receiptRepository.GetContext());
                albumRepository = new Repository<Album>(receiptRepository.GetContext());
                providerRepository = new Repository<Provider>(receiptRepository.GetContext());

                RetriveData();

                if (id != null)
                {
                    lblId.Text = "Số phiếu: " + id;

                    //gridView1.CheckLoaded();    //finish grid initialization

                    var receipt = receiptRepository.GetById((int)id);
                        //Common.GetReceiptById(id, db);
                    if (receipt != null)
                    {
                        dateEdit1.EditValue = receipt.ReceiptDate;
                        //lblDate.Text = receipt.ReceiptDate.ToString();
                        lupProvider.EditValue = receipt.ProviderId;

                        if (receipt.ReceiptDetails.Count>0)
                            InitDataTable(receipt);
                    }
                }
                else
                {
                    this.layoutId.HideToCustomization();
                    dateEdit1.EditValue = DateTime.Now;
                    //lblDate.Text = DateTime.Now.ToString();
                }

                btnCancel.CausesValidation = false;
            }
            catch (Exception)
            {
                this.Close();
                throw;
            }
        }

        private void RetriveData()
        {
            if (dt == null)
                bindingSourceReceiptDetail.DataSource = CreateDataTable();
            else
            {
                bindingSourceReceiptDetail.DataSource = dt;
            }

            bindingSourceProvider.DataSource = providerRepository.GetAll()
                .OrderByDescending(p => p.ProviderId);
                //Common.GetProviders(db);
 	        lupProvider.ItemIndex = 0;
            
            bindingSourceTitle.DataSource = albumRepository.GetAll()
                .Where(a => a.Deleted == null || a.Deleted == false)
                .OrderByDescending(a => a.AlbumId);
                //Common.GetAlbums(db);
        }

        private void InitDataTable(Receipt receipt)
        {
            foreach (var item in receipt.ReceiptDetails)
            {
                DataRow row = dt.NewRow();
                
                row["Title"] = item.AlbumId;
                row["UnitPrice"] = item.UnitPrice;
                row["Quantity"] = item.Quantity;
                row["Price"] = item.UnitPrice * item.Quantity;
                row["ReceiptDetailId"] = item.ReceiptDetailId;
                dt.Rows.Add(row);
            }
            dt.AcceptChanges();
        }

        private DataTable CreateDataTable()
        {
            dt = new DataTable("ReceiptDetail");
            dt.BeginInit();
            dt.Columns.Add("Title");
            dt.Columns.Add("UnitPrice", System.Type.GetType("System.Decimal"));
            dt.Columns.Add("Quantity", System.Type.GetType("System.Int32"));
            dt.Columns.Add("Price", System.Type.GetType("System.Decimal"));
            dt.Columns.Add("ReceiptDetailId", System.Type.GetType("System.Int32"));
            dt.EndInit();
            return dt;
        }

        #region "Button click"
        private void btnAccept_Click(object sender, EventArgs e)
        {
            try
            {
                //validate control
                this.ValidateChildren();

                if (ErrorProvider1.HasErrors)
                {
                    foreach (var item in ErrorProvider1.GetControlsWithError())
                    {
                        item.Focus();
                        Common.ShowErrorBox(ErrorProvider1.GetError(item));
                        return;
                    }
                }

                if (gridView1.RowCount == 0)
                    if (Common.ShowQuestionBox
                        ("Chưa có album trong phiếu. Tiếp tục ?", "okcancel") ==
                        DialogResult.Cancel) return;

                //check duplicate
                if (!CheckDuplicate()) return;

                //switch
                if (id != null) Edit();
                else Insert();
            }
            catch (Exception)
            {
                throw;
            }
        }

        private bool CheckDuplicate()
        {
            for (int i = 0; i < gridView1.RowCount - 1; i++)
            {
                for (int j = i + 1; j < gridView1.RowCount; j++)
                {
                    if (gridView1.GetDataRow(i)["Title"].ToString() ==
                        gridView1.GetDataRow(j)["Title"].ToString())
                    {
                        string str = "Trùng dữ liệu : " +
                            repositoryItemLookUpEdit1.GetDisplayText(gridView1.GetDataRow(i)["Title"]) +
                            " đã có. Tiếp tục ?";

                        if (Common.ShowQuestionBox(str, "okcancel") == DialogResult.OK)
                        {
                            return true;
                            //i = gridView1.RowCount - 1;
                            //break;
                        }
                        else
                        {
                            gridView1.FocusedRowHandle = i;
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            try
            {
                if (id != null)
                {
                    DataTable dtChange = dt.GetChanges();
                    var receipt = receiptRepository.GetById((int)id);
                    //Common.GetReceiptById(id, db);

                    if (dtChange != null ||
                        receipt.ProviderId != Convert.ToInt32(lupProvider.EditValue) ||
                        receipt.ReceiptDate.Date != dateEdit1.DateTime.Date)
                    {
                        DialogResult rs = Common.ShowQuestionBox("Lưu thay đổi ? ", "yesnocancel");
                        if (rs == DialogResult.Yes)
                            btnAccept.PerformClick();
                        else if (rs == DialogResult.Cancel)
                            return;
                    }
                }
                else
                {
                    DialogResult rs = Common.ShowQuestionBox("Lưu phiếu ? ", "yesnocancel");
                    if (rs == DialogResult.Yes)
                        btnAccept.PerformClick();
                    else if (rs == DialogResult.Cancel)
                        return;
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                this.Close();
            }
        }
        
        #endregion

        #region insert
        private void Insert()
        {
            try
            {
                var receipt = new Receipt();
                //create new object
                InitNewReceipt(receipt);

                //insert into database
                receiptRepository.InsertOnSubmit(receipt);
                receiptRepository.SubmitChanges();

                //create Receipt details
                if (gridView1.RowCount>0)
                    CreateReceiptDetails(receipt);
            }
            catch (Exception)
            {
                //Common.ShowErrorBox(ex.Message);
                this.Close();
                throw;
            }

            Common.ShowInfomationBox("Thêm thành công.");

            this.DialogResult = DialogResult.OK;
        }

        private void InitNewReceipt(Receipt receipt)
        {
            receipt.ReceiptDate = dateEdit1.DateTime;
            //receipt.ReceiptDate = Convert.ToDateTime(lblDate.Text);
            receipt.Provider = providerRepository.GetById(Convert.ToInt32(lupProvider.EditValue));
            //receipt.Provider = Common.GetProviderById(Convert.ToInt32(lupProvider.EditValue), db);
            receipt.Total = GetTotal();
        }

        private decimal GetTotal()
        {
            return Convert.ToDecimal(gridView1.Columns["Price"].SummaryItem.SummaryValue);
        }

        private void CreateReceiptDetails(Receipt receipt)
        {
            ReceiptDetail receiptDetail;
            for (int i = 0; i < gridView1.RowCount; i++)
            {
                var row = gridView1.GetDataRow(i);
                receiptDetail = new ReceiptDetail();

                receiptDetail.Quantity = Convert.ToInt32(row["Quantity"]);
                receiptDetail.UnitPrice = Convert.ToDecimal(row["UnitPrice"]);
                receiptDetail.Receipt = receipt;
                receiptDetail.Album = albumRepository.GetById(Convert.ToInt32(row["Title"]));
                
                rdRepository.InsertOnSubmit(receiptDetail);
            }
            rdRepository.SubmitChanges();
        }
        #endregion

        private void gridView1_InitNewRow(object sender, DevExpress.XtraGrid.Views.Grid.InitNewRowEventArgs e)
        {
	        DataRow row = gridView1.GetDataRow(e.RowHandle);
	        row["Quantity"] = 1;
            row["UnitPrice"] = 1;
        }

        private void gridView1_ValidateRow(object sender, DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs e)
        {
            ColumnView view = (ColumnView)sender;
            var colTitle = view.Columns["Title"];
            var colQuantity = view.Columns["Quantity"];
            var colUnitPrice = view.Columns["UnitPrice"];

            //get value
            string title = view.GetRowCellValue(e.RowHandle, colTitle).ToString();

            //validity criterion
            if (title.Length == 0)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colTitle, "Chưa chọn album");
            }
            if (view.GetRowCellValue(e.RowHandle, colUnitPrice).ToString().Length == 0)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colUnitPrice, "Chưa nhập giá");
            }
            else if (Convert.ToDecimal(view.GetRowCellValue(e.RowHandle, colUnitPrice)) < 1
                || Convert.ToDecimal(view.GetRowCellValue(e.RowHandle, colUnitPrice)) > 100)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colUnitPrice, "1-100");
            }
            if (view.GetRowCellValue(e.RowHandle, colQuantity).ToString().Length == 0)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colQuantity, "Chưa nhập số lượng");
            }
            else if (Convert.ToInt32(view.GetRowCellValue(e.RowHandle, colQuantity)) < 1)
            {
                e.Valid = false;

                //set errors with specific descriptions for the columns
                view.SetColumnError(colQuantity, "Số lượng phải lớn hơn 0");
            }

            //if (gridView1.HasColumnErrors)
            //    return;

            //for (int i = 0; i < gridView1.RowCount; i++)
            //    if (i != e.RowHandle)
            //    {
            //        DataRow row = gridView1.GetDataRow(i);
            //        if (Convert.ToInt32(row["Title"]) == Convert.ToInt32(gridView1.GetRowCellValue(e.RowHandle, "Title")))
            //        {
            //            row["Quantity"] = Convert.ToInt32(row["Quantity"]) +
            //                Convert.ToInt32(gridView1.GetRowCellValue(e.RowHandle, "Quantity"));
            //            row["Price"] = Convert.ToInt32(row["Quantity"]) *
            //                Convert.ToDecimal(row["UnitPrice"]);
            //            gridView1.DeleteRow(e.RowHandle);
            //            gridControl1.Update();
            //            return;
            //        }
            //    }
        }

        private void gridView1_InvalidRowException(object sender, InvalidRowExceptionEventArgs e)
        {
            e.ExceptionMode = ExceptionMode.NoAction;
            if (gridView1.HasColumnErrors)
            {
                if (gridView1.GetColumnError(gridView1.Columns["Title"]) != "")
                    Common.ShowErrorBox(gridView1.GetColumnError(gridView1.Columns["Title"]));
                else if (gridView1.GetColumnError(gridView1.Columns["Quantity"]) != "")
                    Common.ShowErrorBox(gridView1.GetColumnError(gridView1.Columns["Quantity"]));
                else if (gridView1.GetColumnError(gridView1.Columns["UnitPrice"]) != "")
                    Common.ShowErrorBox(gridView1.GetColumnError(gridView1.Columns["UnitPrice"]));
            }
        }

        private void repositoryItemLookUpEdit1_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                LookUpEdit lup = sender as LookUpEdit;

                var album = albumRepository.GetById(Convert.ToInt32(lup.EditValue));
                //Common.GetAlbumById(Convert.ToInt32(lup.EditValue), db);
                var unitPrice = album.Price;
                var quantity = Convert.ToInt32(gridView1.GetFocusedRowCellValue("Quantity"));

                gridView1.SetFocusedRowCellValue("UnitPrice", album.Price);
                gridView1.SetFocusedRowCellValue("Price", unitPrice * quantity);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void repositoryItemCalcEditQuantity_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                CalcEdit calc = sender as CalcEdit;
                
                var unitPrice = gridView1.GetFocusedRowCellValue("UnitPrice");
                var quantity = Convert.ToInt32(calc.EditValue);

                if (unitPrice.ToString().Length == 0)
                    return;
                else if (quantity < 1 || Convert.ToDecimal(unitPrice) < 1)
                    return;

                gridView1.SetFocusedRowCellValue("Price", Convert.ToDecimal(unitPrice) * quantity);
            }
            catch (Exception)
            {
                throw;
                //Common.ShowErrorBox(ex.Message);
            }
        }

        private void repositoryItemCalcEditUnitPrice_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                CalcEdit calc = sender as CalcEdit;
                var unitPrice = Convert.ToDecimal(calc.EditValue);
                var quantity = gridView1.GetFocusedRowCellValue("Quantity");

                if (quantity.ToString().Length == 0)
                    return;
                else if (Convert.ToInt32(quantity) < 1 || unitPrice < 1)
                    return;

                gridView1.SetFocusedRowCellValue("Price", unitPrice * Convert.ToInt32(quantity));
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void repositoryItemBtnDelete_Click(object sender, EventArgs e)
        {
            gridView1.DeleteSelectedRows();
            gridControl1.Update();
        }

        #region edit
        private void Edit()
        {
            try
            {
                DataTable dtChange = dt.GetChanges();
                var receipt = receiptRepository.GetById((int)id);
                    //Common.GetReceiptById(id, db);
                //if grid and provider have changed
                if (dtChange == null && 
                    receipt.ProviderId == Convert.ToInt32(lupProvider.EditValue) &&
                    receipt.ReceiptDate.Date == dateEdit1.DateTime.Date)
                {
                    this.Close();
                    return;
                }

                DialogResult result = Common.ShowQuestionBox("Sửa phiếu nhập " 
                    + id + " ?", "okcancel");

                if (result == DialogResult.OK)
                {
                    InitNewReceipt(receipt);

                    receiptRepository.SubmitChanges();

                    if (dtChange != null)
                    {
                        if (gridView1.RowCount > 0) //lacked deleted row
                            EditReceiptDetails(receipt, dtChange);
                        else if (gridView1.RowCount == 0) //delete all
                            DeleteAllReceiptDetails(receipt);
                    }

                    Common.ShowInfomationBox("Sửa thành công.");

                    this.DialogResult = DialogResult.OK;
                }

            }
            catch (Exception)
            {
                //Common.ShowErrorBox(ex.Message);
                this.Close();
                throw;
            }
        }

        private void EditReceiptDetails(Receipt receipt, DataTable dtChange)
        {
            ReceiptDetail receiptDetail;
            //row dont have receiptdetailid will insert, any else edit
            foreach (DataRow row in dtChange.Rows)
            {
                if (row.RowState == DataRowState.Deleted)
                {
                    int? receiptDetailId = Convert.ToInt32(row["ReceiptDetailId", DataRowVersion.Original]);

                    receiptDetail = rdRepository.GetById((int)receiptDetailId);
                        //Common.GetReceiptDetailById(receiptDetailId, db);

                    rdRepository.DeleteOnSubmit(receiptDetail);
                    //db.ReceiptDetails.DeleteOnSubmit(receiptDetail);
                }
                else if (row["ReceiptDetailId"].ToString()=="")
                {
                    receiptDetail = new ReceiptDetail();

                    receiptDetail.Quantity = Convert.ToInt32(row["Quantity"]);
                    receiptDetail.UnitPrice = Convert.ToDecimal(row["UnitPrice"]);
                    receiptDetail.Receipt = receipt;
                    //receiptDetail.Receipt = receipt;
                    receiptDetail.Album = albumRepository.GetById(Convert.ToInt32(row["Title"]));
                    //receiptDetail.Album = Common.GetAlbumById(Convert.ToInt32(row["Title"]), db);

                    rdRepository.InsertOnSubmit(receiptDetail);
                    //db.ReceiptDetails.InsertOnSubmit(receiptDetail);
                }
                else
                {
                    receiptDetail = rdRepository.GetById(Convert.ToInt32(row["ReceiptDetailId"]));
                        //Common.GetReceiptDetailById(receiptDetailId, db);

                    if (receiptDetail == null)
                        continue;

                    receiptDetail.Quantity = Convert.ToInt32(row["Quantity"]);
                    receiptDetail.UnitPrice = Convert.ToDecimal(row["UnitPrice"]);
                    receiptDetail.Receipt = receipt; //dont need edit
                    receiptDetail.Album = albumRepository.GetById(Convert.ToInt32(row["Title"]));
                    //receiptDetail.Album = Common.GetAlbumById(Convert.ToInt32(row["Title"]), db);
                }
            }

            rdRepository.SubmitChanges();
            //db.SubmitChanges();
        }

        private void DeleteAllReceiptDetails(Receipt receipt)
        {
            rdRepository.DeleteAllOnSubmit(receipt.ReceiptDetails);
            rdRepository.SubmitChanges();
            //db.ReceiptDetails.DeleteAllOnSubmit(receipt.ReceiptDetails);
            //db.SubmitChanges();
        }
        #endregion

        private void AcceptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.btnAccept.PerformClick();
        }

        private void CancelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.btnCancel.PerformClick();
        }

        private void Check(object sender, CancelEventArgs e)
        {
            string str = null;

            //title required
            if (sender.GetType().Name == "DateEdit")
            {
                DateEdit de = (DateEdit)sender;
                if (de.Text.Trim().Length == 0)
                    str = "Chưa nhập ngày";
            }
            ErrorProvider1.SetIconAlignment((Control)sender, ErrorIconAlignment.MiddleRight);
            ErrorProvider1.SetError((Control)sender, str);
        }

        private void gridView1_ValidatingEditor(object sender, BaseContainerValidateEditorEventArgs e)
        {
            if (gridView1.FocusedColumn.Name == "colTitle")
            {
                //validity criterion
                if (e.Value.ToString() != "")
                {
                    gridView1.SetColumnError(gridView1.Columns["Title"], "");
                }
            }
            else if (gridView1.FocusedColumn.Name == "colQuantity")
            {
                if (Convert.ToInt32(e.Value) > 0)
                {
                    gridView1.SetColumnError(gridView1.Columns["Quantity"], "");
                }
            }
            else if (gridView1.FocusedColumn.Name == "colUnitPrice")
            {
                if (Convert.ToInt32(e.Value) > 0)
                {
                    gridView1.SetColumnError(gridView1.Columns["UnitPrice"], "");
                }
            }
        }
    }
}